
#if defined _partypalooza_included
	#endinput
#endif
#define _partypalooza_included

#include <amxmodx>
#include <fun>

#if !defined _partypalooza_core
	#pragma reqlib "partypalooza"
#endif

#if !defined MAX_PLAYERS
	#define MAX_PLAYERS 33
#endif

#define MAX_PRECACHE 512

enum ( <<= 1 )
{
	P_FLAG_A = 1,
	P_FLAG_B,
	P_FLAG_C,
	P_FLAG_D,
	P_FLAG_E,
	P_FLAG_F,
	P_FLAG_G,
	P_FLAG_H,
	P_FLAG_I,
	P_FLAG_J,
	P_FLAG_K,
	P_FLAG_L,
	P_FLAG_M,
	P_FLAG_N,
	P_FLAG_O,
	P_FLAG_P,
	P_FLAG_Q,
	P_FLAG_R,
	P_FLAG_S,
	P_FLAG_T,
	P_FLAG_U,
	P_FLAG_V,
	P_FLAG_W,
	P_FLAG_X,
	P_FLAG_Y,
	P_FLAG_Z,
}

//#define P_FLAG_A        (1<<0)        /* flag "a" */
//#define P_FLAG_B        (1<<1)        /* flag "b" */
//#define P_FLAG_C        (1<<2)        /* flag "c" */
//#define P_FLAG_D        (1<<3)        /* flag "d" */
//#define P_FLAG_E        (1<<4)        /* flag "e" */
//#define P_FLAG_F        (1<<5)        /* flag "f" */
//#define P_FLAG_G        (1<<6)        /* flag "g" */
//#define P_FLAG_H        (1<<7)        /* flag "h" */
//#define P_FLAG_I        (1<<8)        /* flag "i" */
//#define P_FLAG_J        (1<<9)        /* flag "j" */
//#define P_FLAG_K        (1<<10)       /* flag "k" */
//#define P_FLAG_L        (1<<11)       /* flag "l" */
//#define P_FLAG_M        (1<<12)       /* flag "m" */
//#define P_FLAG_N        (1<<13)       /* flag "n" */
//#define P_FLAG_O        (1<<14)       /* flag "o" */
//#define P_FLAG_P        (1<<15)       /* flag "p" */
//#define P_FLAG_Q        (1<<16)       /* flag "q" */
//#define P_FLAG_R        (1<<17)       /* flag "r" */
//#define P_FLAG_S        (1<<18)       /* flag "s" */
//#define P_FLAG_T        (1<<19)       /* flag "t" */
//#define P_FLAG_U        (1<<20)       /* flag "u" */
//#define P_FLAG_V        (1<<21)       /* flag "v" */
//#define P_FLAG_W        (1<<22)       /* flag "w" */
//#define P_FLAG_X        (1<<23)       /* flag "x" */
//#define P_FLAG_Y        (1<<24)       /* flag "y" */
//#define P_FLAG_Z        (1<<25)       /* flag "z" */


enum
{
	PINFO_CONNECT,						//start bools
	PINFO_SOLID,
	PINFO_BOOL_END,

	PINFO_TEAM = PINFO_BOOL_END,		//start shorts
	PINFO_SPEC,
	PINFO_GLOW_RED,
	PINFO_GLOW_GREEN,
	PINFO_GLOW_BLUE,
	PINFO_ALPHA,
	PINFO_LASTHIT,
	PINFO_SHORT_END,

	PINFO_STATUS = PINFO_SHORT_END,		//start longs
	PINFO_SPEED,
	PINFO_HEALTH,
	PINFO_LIVES,
	PINFO_POINTS,
	PINFO_WEAPONS,
	PINFO_KILLS,
	PINFO_DEATHS,
	PINFO_OFF_SPEED,
	PINFO_MENU_WEAP,
	PINFO_CURRENT_WEAP,
	PINFO_LAST_WEAP,
	PINFO_LONG_END,
}

enum
{
	FORW_INIT = P_FLAG_A,
	FORW_PLAYER_SPAWN = P_FLAG_B,
	FORW_START = P_FLAG_C,
	FORW_PLAYER_DEATH = P_FLAG_D,
	FORW_END = P_FLAG_E,
	FORW_LOOP = P_FLAG_F,
	FORW_PLAYER_DAMAGE = P_FLAG_G,
}

enum
{
	TEAM_FFA = P_FLAG_A,
	TEAM_EVEN = P_FLAG_B,
	TEAM_ONEvALL = P_FLAG_C,
	TEAM_TWO = P_FLAG_D,
	TEAM_ALL = P_FLAG_E,
}

enum PLAYER_SELECT
{
	PLAYER_NONE =       0,
	PLAYER_ALIVE =      P_FLAG_A,
	PLAYER_DEAD =       P_FLAG_B,
	PLAYER_REAL =       P_FLAG_C,
	PLAYER_BOT =        P_FLAG_D,
	PLAYER_INTEAM =     P_FLAG_E,
	PLAYER_GOD =        P_FLAG_F,
	PLAYER_MORTAL =     P_FLAG_G,
	PLAYER_NOHLTV =     P_FLAG_H,
	PLAYER_NOTEAM =     P_FLAG_I,
	PLAYER_HELPHUD =    P_FLAG_J,
	PLAYER_RELOAD =     P_FLAG_K,
	PLAYER_SPECTATOR =     P_FLAG_L,
}

enum
{
	VOTE_NONE,
	VOTE_RANDOM,
	VOTE_SELECT,
	VOTE_GAMEID,
}

enum
{
	WEAPON_INTS = 0,
	WEAPON_OVERRIDE = WEAPON_INTS,
	WEAPON_TYPE,
	WEAPON_RUN_SPEED,                   //awp = 210, knife = 250, average of all guns = 240
	WEAPON_CLIP_AMMO,
	WEAPON_DRAW_ANIM,
	WEAPON_IDLE_ANIM,
	WEAPON_FIRE_ANIM,
	WEAPON_FIRE2_ANIM,
	WEAPON_RELOAD_ANIM,
	WEAPON_FIRE_DAMAGE,                 //awp ~114, shotgun ~17, deagle ~45
	WEAPON_FIRE2_DAMAGE,                //awp ~114, shotgun ~17, deagle ~45
	WEAPON_FIRE_BULLETS,                //how many bullets to fire with attack
	WEAPON_FIRE2_BULLETS,               //how many bullets to fire with attack2
	WEAPON_RELOAD_BULLETS,              //how many bullets to reload, stops at clipsize
	WEAPON_FIRE_BITSUM,
	WEAPON_FIRE2_BITSUM,
	WEAPON_FIRE_DIST,                   //guns = 8192, pistols = 4096, shotgun = 3000, knife slash = 48, knife stab = 32
	WEAPON_FIRE2_DIST,                  //  two exceptions are glock and dualies have 8192

	WEAPON_FLOATS,
	WEAPON_RECOIL=WEAPON_FLOATS,
	WEAPON_SPREAD,
	WEAPON_FIRE_SPREAD,              //how many shots are spread
	WEAPON_FIRE2_SPREAD,
	WEAPON_FIRE_TIME,
	WEAPON_FIRE2_TIME,
	WEAPON_RELOAD_TIME,
	WEAPON_MAX_INFO
}
enum
{
	WEAPON_NAME,
	WEAPON_VMODEL,
	WEAPON_PMODEL,
	WEAPON_FIRE_SOUND,
	WEAPON_FIRE2_SOUND,
	WEAPON_RELOAD_SOUND,
	WEAPON_MAX_STRING
}
enum
{
	FIRE_NONE =          0,
	FIRE_BULLET =        P_FLAG_A,
	FIRE_MELEE =         P_FLAG_B,
	FIRE_PROJECTILE =    P_FLAG_C,
	FIRE_WHILE_RELOAD =  P_FLAG_D,
	FIRE_MUZZLEFLASH =   P_FLAG_E,
	FIRE_FORWARD =       P_FLAG_F,
	FIRE_PENETRATE =       P_FLAG_G,
}
enum WeaponType
{
	WEAP_GUN =           P_FLAG_A,
	WEAP_MELEE =         P_FLAG_B,
	WEAP_MISC =          P_FLAG_C,
	WEAP_WEAK =          P_FLAG_D,
	WEAP_MILD =          P_FLAG_E,
	WEAP_STRONG =        P_FLAG_F,
	WEAP_UBER =          P_FLAG_G,
}
enum
{
	WEAPINFO_WEAPON,
	WEAPINFO_CLIP,
	WEAPINFO_BACKPACK,
	WEAPINFO_MAX
}

enum AOE_FLAGS
{
    AOE_NORMAL = 0,              //normal radial area of effect attack
    AOE_IGNORE = P_FLAG_A,       //ignore attacker
    AOE_MAXDAM = P_FLAG_B,       //if within radius, do max damage
    AOE_ATEAM =  P_FLAG_C,       //only deal with the attackers teammates
    AOE_VTEAM =  P_FLAG_D,       //deal with enemies of the attacker only
}

#define m_flNextAttack	83

#define VECTOR_CONE_1DEGREES	0.00873
#define VECTOR_CONE_2DEGREES	0.01745
#define VECTOR_CONE_3DEGREES	0.02618
#define VECTOR_CONE_4DEGREES	0.03490
#define VECTOR_CONE_5DEGREES	0.04362
#define VECTOR_CONE_6DEGREES	0.05234
#define VECTOR_CONE_7DEGREES	0.06105
#define VECTOR_CONE_8DEGREES	0.06976
#define VECTOR_CONE_9DEGREES	0.07846
#define VECTOR_CONE_10DEGREES	0.08716
#define VECTOR_CONE_15DEGREES	0.13053
#define VECTOR_CONE_20DEGREES	0.17365

#define MAX_GAMES 50
#define GAMEID_SELECT -3
#define GAMEID_RANDOM -2
#define GAMEID_NULL -1

#define AREA_RANDOM -2
#define AREA_NULL -1
#define AREA_WAIT 0
#define AREA_ONE 1

#define MAX_TEAMS 16
#define TEAM_NULL MAX_TEAMS

#define MODE_RANDOM -2
#define MODE_NULL -1
#define MODE_NORMAL 0

#define SPEC_NULL -1

#define ENT_NULL -1
#define ENT_SPAWN 0
#define ENT_SPEC 1

#define SZ_NAME_LEN 32
#define SZ_MODEL_LEN 52

#define AREA_DM (1<<ENT_SPAWN)
#define AREA_SPEC (1<<ENT_SPEC)

stock const entity_player[] = "player";
stock const Default[] = "default";
stock const DefaultFireSound[] = "weapons/elite_fire.wav";
stock const DefaultFire2Sound[] = "weapons/zoom.wav";
stock const DefaultReloadSound[] = "weapons/generic_reload";

#define SECONDS_TO_SCREENFADE_UNITS(%1) floatround(float((1<<12)) * (%1))

stock const _TeamColors[MAX_TEAMS][3] = {
	{0,255,0},		//green - ct
	{255,0,0},		//red - t
	{0,64,255},		//blue - ct 0,0,255
	{255,255,0},	//yellow - t
	{135,206,250},	//sky blue - ct
	{255,140,0},	//orange - t
	{0,255,255},	//cyan - ct
	{250,128,114},	//salmon - t
	{127,255,127},		//kiwi - ct 127,255,0
	{139,69,19},	//brown - t
	{128,128,128},	//grey - ct
	{255,105,180},	//pink - t
	{0,100,0},		//dark green - ct
	{148,0,211},	//purple - t
	{255,255,255},	//white - ct
	{184,134,11}	//gold - t
}
stock const _TeamBlood[MAX_TEAMS] = {
	178,	//green - ct
	250,	//red - t
	208,	//blue - ct
	111,	//yellow - t
	244,	//sky blue - ct
	232,	//orange - t
	176,	//cyan - ct
	127,	//salmon - t
	242,	//kiwi - ct
	204,	//brown - t
	9,		//grey - ct
	144,	//pink - t
	189,	//dark green - ct
	33,	//purple - t
	15,	//white - ct
	199	//gold - t
}
stock const TeamNames[MAX_TEAMS][] = {
	"Green",	//green
	"Red",	//red
	"Blue",	//blue
	"Yellow",	//yellow
	"Sky",	//sky blue
	"Orange",	//orange
	"Cyan",	//cyan
	"Salmon",	//salmon
	"Kiwi",	//kiwi
	"Brown",	//brown
	"Grey",	//grey
	"Pink",	//pink
	"Forest",	//dark green
	"Purple",	//purple
	"White",	//white
	"Gold"	//gold
}
#define TeamColor(%1,%2) _TeamColors[%1 % MAX_TEAMS][%2]
#define TeamColors[%1][%2] _TeamColors[%1 % MAX_TEAMS][%2]

native PartyPlayerRespawn(id);
native PartyPlayerKill(id, killer=0, weaponname[]="", headshot=0);

native PartyPlayerInfo(id, pinfo);
native PartyPlayerSetInfo(id, pinfo, newinfo);
native PartyTeamSetInfo(team, pinfo, newinfo);

native PartyPlayerWin(id);
native PartyPlayerLose(id);

native PartyTeamWin(team);
native PartyTeamLose(team);

native PartyGetTeams(teams[MAX_TEAMS], &tnum, const PLAYER_SELECT:flags=PLAYER_NONE);
native PartyGetPlayers(players[MAX_PLAYERS], &pnum, const PLAYER_SELECT:flags=PLAYER_NONE, const team=-1);
native PartyGetNextPlayer(&id, const PLAYER_SELECT:flags=PLAYER_NONE, const team=-1);

native PartyAreaName( Name[], len );

//set id to -1 to set for all players
native PartyGameHelp( id=-1, HelpMsg[] );
//help message is shown to all teams
native PartyModeHelp( HelpMsg[] );
//this is a macro for setting game help to all players
#define PartyHelpMsg(%1) PartyGameHelp(_,%1)

//Use a bitsum for the entities required for the current game
native RegisterGame( Name[], Teams, EntsSum );

native RegisterMode( Name[] );

native RegisterSpec( Name[] );
forward PartySpecInit( specid, id );
forward PartySpecEnd( id );

//Precaches Model, should only be used during PartyPrecache
native RegisterEnt( Name[], Model[] );

native RegisterWeapon( Name[], Override, WeaponType:Type, ViewModel[], PlayerModel[]="default" );
native WeaponSetString( weapon, weapon_string, set_string[] );
native WeaponGetString( weapon, weapon_string, get_string[], len );
native WeaponSetInfo( weapon, weapon_info, set_info );
native WeaponSetFloat( weapon, weapon_info, Float:set_info );
native WeaponGetInfo( weapon, weapon_info );
native WeaponGetFloat( weapon, weapon_info, &Float:info );
native CustomWeapons();

forward PartyPrecache();
native PartyPrecacheModel( model[], any:... );
native PartyPrecacheSound( sound[], any:... );

native PartyPlayerSetModel( id, model[] );
//Entites assigned to a player will be given the same glow that the player has
native PartyAssignEnt(id, entity);
native PartyUnassignEnt(id, entity);

forward PartyInit();

forward GameInit(post, gameid, mode);
forward GameStart(post, gameid, mode);
forward GameEnd(post, gameid, mode);
forward GameLoop(gameid, mode);

forward GamePlayerSpawn(post, gameid, mode, id);
forward GamePlayerDeath(post, gameid, mode, id, killer);
forward GamePlayerDamage(post, gameid, mode, id, attacker, damage, pp_weapon, hitgroup);

forward CustomWeaponFire(weapon, id, projectile);
forward CustomWeaponFire2(weapon, id, projectile);

native PartyDamage(pp_weapon, victim, attacker, damage, Attack[], weapon_icon[]="", hitzone=HIT_GENERIC);
native AoEDamage(pp_weapon, attacker, Float:origin[3], radius, maxdamage, Attack[], AOE_FLAGS:aoe_flags=AOE_NORMAL, weapon_icon[]="");
native LineDamage(pp_weapon, attacker, Float:start[3], Float:end[3], radius, maxdamage, Attack[], weapon_icon[]="");

//Set ent to 0 to just get Origin and Angles
native PartyMoveEnt(ent, ent_type, Float:Origin[3], Float:Angles[3]);

//attempts to unstuck a player
native PartyUnstuck(id);

enum
{
	PP_NONE = -1,
	PP_P228,
	PP_SCOUT,
	PP_HEGRENADE,
	PP_XM1014,
	PP_C4,
	PP_MAC10,
	PP_AUG,
	PP_SMOKEGRENADE,
	PP_ELITE,
	PP_FIVESEVEN,
	PP_UMP45,
	PP_SG550,
	PP_GALIL,
	PP_FAMAS,
	PP_USP,
	PP_GLOCK18,
	PP_AWP,
	PP_MP5NAVY,
	PP_M249,
	PP_M3,
	PP_M4A1,
	PP_TMP,
	PP_G3SG1,
	PP_FLASHBANG,
	PP_DEAGLE,
	PP_SG552,
	PP_AK47,
	PP_KNIFE,
	PP_P90,
	PP_MAX_DEFAULT
}

stock GiveWeaponNames[][] = {
	"",
	"weapon_p228",
	"",
	"weapon_scout",
	"weapon_hegrenade",
	"weapon_xm1014",
	"weapon_c4",
	"weapon_mac10",
	"weapon_aug",
	"weapon_smokegrenade",
	"weapon_elite",
	"weapon_fiveseven",
	"weapon_ump45",
	"weapon_sg550",
	"weapon_galil",
	"weapon_famas",
	"weapon_usp",
	"weapon_glock18",
	"weapon_awp",
	"weapon_mp5navy",
	"weapon_m249",
	"weapon_m3",
	"weapon_m4a1",
	"weapon_tmp",
	"weapon_g3sg1",
	"weapon_flashbang",
	"weapon_deagle",
	"weapon_sg552",
	"weapon_ak47",
	"weapon_knife",
	"weapon_p90"
}

#define PRIMARY_WEAPONS ((1<<PP_SCOUT) | (1<<PP_XM1014) | (1<<PP_MAC10) | (1<<PP_AUG) | (1<<PP_UMP45) | (1<<PP_SG550) | (1<<PP_GALIL) | (1<<PP_FAMAS) | (1<<PP_AWP) | (1<<PP_MP5NAVY) | (1<<PP_M249) | (1<<PP_M3) | (1<<PP_M4A1) | (1<<PP_TMP) | (1<<PP_G3SG1) | (1<<PP_SG552) | (1<<PP_AK47) | (1<<PP_P90))
#define SECONDARY_WEAPONS ((1<<PP_P228) | (1<<PP_ELITE) | (1<<PP_FIVESEVEN) | (1<<PP_USP) | (1<<PP_GLOCK18) | (1<<PP_DEAGLE))
#define TERTIARY_WEAPONS (1<<PP_KNIFE)
#define QUATERNARY_WEAPONS ((1<<PP_HEGRENADE) | (1<<PP_SMOKEGRENADE) | (1<<PP_FLASHBANG))
#define QUINARY_WEAPONS (1<<PP_C4)

#define NO_WEAPONS 0
#define ALL_WEAPONS (PRIMARY_WEAPONS|SECONDARY_WEAPONS|TERTIARY_WEAPONS|QUATERNARY_WEAPONS|QUINARY_WEAPONS)
#define GUN_WEAPONS (PRIMARY_WEAPONS|SECONDARY_WEAPONS)
#define PISTOL_WEAPONS (SECONDARY_WEAPONS)
#define KNIFE_WEAPONS (TERTIARY_WEAPONS)
#define SHOTGUN_WEAPONS ((1<<PP_XM1014) | (1<<PP_M3))
#define SMG_WEAPONS ((1<<PP_MAC10) | (1<<PP_UMP45) | (1<<PP_MP5NAVY) | (1<<PP_TMP) | (1<<PP_P90))
#define RIFLE_WEAPONS ((1<<PP_AUG) | (1<<PP_GALIL) | (1<<PP_FAMAS) | (1<<PP_M4A1) | (1<<PP_SG552) | (1<<PP_AK47))
#define SNIPER_WEAPONS ((1<<PP_SCOUT) | (1<<PP_SG550) | (1<<PP_AWP) | (1<<PP_G3SG1))
#define MACHINE_WEAPONS (1<<PP_M249)
#define GRENADE_WEAPONS (QUATERNARY_WEAPONS)
#define BOMB_WEAPONS (QUINARY_WEAPONS)

enum (+=32)
{
	TASK_RELOAD = 2500,
}

//Player will be shown a menu for all weapons supplied.
//Note for guns, this will give 512 ammo
native PartyWeaponMenu(id, weapon_choice1, weapon_choice2, ...);
//Player will be shown a menu with all weapons matching type
//Note for guns, this will give 512 ammo
native PartyWeaponMenuType(id, WeaponType:type);
//Player will be given the weapon with set ammo
native PartyGiveWeapon(id, pp_weapon, ammo=512);
//Strips all weapons from id
native PartyStripWeapons(id);


stock RandomBit( bitsum )
{
	new randbit;
	do randbit = (1<<random(32));
	while( !( bitsum & randbit ) );
	return randbit;
}
stock RandomBit2( bitsum )
{
	new randbit;
	do randbit = random(32);
	while( !( bitsum & (1<<randbit) ) );
	return randbit;
}
stock NextBit( bitsum )
{
	for( new i; i<32; i++ )
	{
		if( bitsum & (1<<i) )
			return (1<<i);
	}
	return -1;
}
stock NextBit2( bitsum )
{
	for( new i; i<32; i++ )
	{
		if( bitsum & (1<<i) )
			return i;
	}
	return -1;
}
stock BitCount( bitsum )
{
	new count;
	for( new i; i<32; i++ )
	{
		if( bitsum & (1<<i) )
			count++;
	}
	return count;
}
stock RandomFactor( num )
{
	new randnum;
	do randnum = random(num);
	while( !is_factor(num,randnum) );
	return randnum;
}
stock is_factor( num, factor )
{
	for( new m=2; m<num; m++ )
	{
		if( factor*m == num )
			return true;
	}
	return false;
}
stock is_prime( num )
{
	if( num < 2 )
		return false;
	for( new m=2; m<num; m++ )
	{
		if( num % m == 0 )
			return false;
	}
	return true;
}

// Gets a low/high based on percentage of third out of fourth parameters
#define PartyPercentage(%1,%2,%3,%4) (%1 + ( ( %3 * (%2-%1) ) / %4 ) )
